package edu.uoc.tdp.beans.conexio;

import java.io.Serializable;

/**
 * <b>Descripció :</b><br> Classe NIF. Gestiona documents d'identificació
 * fiscal. <br> Amb utilitats per el pas de DNIs a NIFs.<br> <br> <b>Millores
 * :</b><br> Millora l'anterior classe en el sentit que :<br> - Te constructors
 * i propietats que creen una instància a partir d'un NIF o d'un DNI.<br> -
 * Valida de forma estàtica qualsevol NIF, sigui quina sigui la seva llargaria.
 * No tots els NIFs han de tenir 9 caràcters.<br> - Valida un NIF per
 * instància.<br> - Retorna la lletra d'un NIF a partir d'un DNI donat.<br> <br>
 * <b>Noves implementacions : Març del 2.004 :</b><br> - Mètodes clone(),
 * equals() i toString() <br>
 *
 * @author Jose Luis Monte Galiano (modificat per Norbert Rovira)
 * @version 2004 - 1.3
 *
 * canvis versió 1.2: afegit interface Serializable canvis versió 1.3:
 * modificada validació perquè no accepti NIFs amb 1 sol dígit necessita mínim
 * un dígit i la lletra de control.
 */
public final class NIF implements Cloneable, Serializable {

    /*
     * -------------------------------------- Propietats
     * --------------------------------------
     */
    // NIF.
    private String mNIF;

    /**
     * Retorna el NIF de la instància actual.
     *
     * @return String : Amb el NIF.
     */
    public String getNIF() {
        return mNIF;
    }

    /**
     * Emmagatzema un NIF.
     *
     * @param pNouNIF : Nou NIF a emmagatzemar.
     */
    public void setNIF(String pNouNIF) {
        mNIF = pNouNIF;
    }

    /*
     * -------------------------------------- Constructors.
     * --------------------------------------
     */
    /**
     * Constructor sense paràmetres.
     */
    public NIF() {
        setNIF("");
    }

    /**
     * Constructor amb DNI.
     *
     * @param pDNI : DNI a partir del cual es forma el NIF.
     */
    public NIF(int pDNI) {
        setNIF(String.valueOf(pDNI) + trobarLletraNIF(pDNI));
    }

    /**
     * Constructor amb NIF.
     *
     * @param pNIF : NIF.
     */
    public NIF(String pNIF) {
        if (validar(pNIF)) {
            setNIF(pNIF);
        } else {
            setNIF("");
        }
    }

    /*
     * -------------------------------------- Mètodes públics.
     * --------------------------------------
     */
    /**
     * Mètode de còpia d'objectes. Crea una nova instància de la classe NIF. El
     * valor dels atributs de la nova instància són els mateixos que els
     * d'aquest objecte.
     *
     * @return Object una copia d'aquesta instància de la classe NIF
     */
    @Override
    public Object clone() {
        //redefinim el clone de DNI
        return new NIF(getNIF());
    }

    /**
     * Mètode comparador. Retorna cert si l'objecte passat com a paràmetre és
     * igual a aquest objecte.
     *
     * @param obj : objecte a comparar
     * @return cert si l'objecte passat per paràmetre es considera igual a
     * aquest.
     */
    @Override
    public boolean equals(Object obj) {
        boolean resul = false;
        if ((obj != null) && (obj instanceof NIF)) {
            resul = (getNIF() == ((NIF) obj).getNIF());
        } else {
            resul = false;
        }

        return resul;
    }

    /**
     * Crea una cadena de caràcters amb valor el número de NIF.
     *
     * @return String el número de NIF.
     */
    @Override
    public String toString() {
        return ("NIF : " + getNIF());
    }

    /**
     * Funció que determina si un NIF de la instància actual es o no vàlid.
     *
     * @return Booleà amb VERTADER si el NIF es correcte, i FALS si no ho es.
     */
    public boolean validar() {
        return validar(getNIF());
    }

    /**
     * Funció estàtica que determina si un NIF donat es o no vàlid
     * independentment de la seva llargaria. Millora l'anterior amb el mateix
     * nom en el sentit que un NIF pot tenir una llargaria variable. No sempre
     * un NIF te 9 caràcters.
     *
     * @param pNIF : String que emmagatzema el NIF a validar.
     * @return Booleà amb VERTADER si el NIF es correcte, i FALS si no ho es.
     */
    public static boolean validar(String pNIF) {
        boolean ret = false;
        char a;

        if (pNIF.length() == 0) {
            ret = true;
        } else {
            if (pNIF.length() == 1) {
                ret = false;
            } else {
                a = pNIF.charAt(pNIF.length() - 1);
                if (Character.isLetter(a)) {
                    if (a == trobarLletraNIF(Integer.parseInt(pNIF.substring(0, pNIF.length() - 1))).charAt(0)) {
                        ret = true;
                    }
                } else {
                    ret = false;
                }
            }
        }
        return ret;
    }

    /**
     * Funció estàtica que retorna la lletra de NIF corresponent a un DNI donat.
     *
     * @param pDNI : DNI del que es vol trobar la lletra del NIF.
     * @return String amb la lletra corresponent.
     */
    public static String trobarLletraNIF(int pDNI) {
        String lletres = "TRWAGMYFPDXBNJZSQVHLCKET";
        return lletres.substring((pDNI % 23), (pDNI % 23) + 1);
    }
}

